#ifndef BOARD_H
#define BOARD_H

#include <QMouseEvent>
#include <QWidget>
#include <QPushButton>
#include "chessPieces.h"
#include "step.h"

class Board : public QWidget
{
    Q_OBJECT
public:
    explicit Board(QWidget *parent = nullptr);
    // 游戏是否结束
    bool isGameOver;
    // 所有棋子的数组
    ChessPieces pieces[PIECES_NUM];
    ChessPieces* copyChessPiecesArray(
        const ChessPieces pieces[PIECES_NUM]) const;
    // 当前选中的棋子id
    int selectId;
    // 为true则当前棋盘是上红下黑否则上黑下红
    bool redTopBlackBottom;
    // 标记当前轮到谁走
    bool isRedTurn;
    // 红方悔棋数组
    QVector<QSharedPointer<Step>> redSteps;
    // 黑方悔棋数组
    QVector<QSharedPointer<Step>> blackSteps;
    // 走棋历史记录结构
    typedef struct MoveRecord {
        QSharedPointer<Step> step;
        quint64 boardHash;  // 走棋后的棋盘哈希
        bool isRedTurn;
    } MoveRecord;
    // 走棋历史
    QVector<MoveRecord> moveHistory;
    // 棋子基础权重表
    QMap<PIECES_TYPE, int> PIECE_WEIGHTS;

    // 初始化棋子
    void initPieces();
    // 记录步骤
    void recordMove(QSharedPointer<Step> step);
    // 获取棋子的权重
    int getPieceValue(const ChessPieces& piece) const;
    // 判断是否过河
    bool isCrossedRiver(const ChessPieces& piece) const;
    bool isCrossedRiver(const ChessPieces& piece, int row) const;
    // 判断是否在九宫格
    bool isNinePalaceGrid(const ChessPieces& piece) const;
    // 获取兵的前进方向
    int getforwardDirOfBing(const ChessPieces& piece) const;
    void paintEvent(QPaintEvent *);
    // 绘制移动标记
    void drawMoveMark(QPainter& painter, QSharedPointer<Step> step);
    // 鼠标释放事件
    void mouseReleaseEvent(QMouseEvent *ev);
    // 移动棋子
    virtual bool movePiece(int row, int col, int secondId);
    // 执行移动棋子
    void executeMovePiece(int row, int col, int secondId);
    // 通过点击位置得到棋子行和列
    bool getRowCol(QPoint pt, int& row, int& col);
    // 判断棋子是否能够移动到指定位置
    bool canMove(ChessPieces pieces[PIECES_NUM], int selectId, int row, int col, int secondId);
    // 判断对应棋子类型是否能够移动到指定位置
    bool canMoveCHE(ChessPieces pieces[PIECES_NUM], int selectId, int row, int col, int secondId);
    bool canMoveBING(ChessPieces pieces[PIECES_NUM], int selectId, int row, int col, int secondId);
    bool canMoveJIANG(ChessPieces pieces[PIECES_NUM], int selectId, int row, int col, int secondId);
    bool canMoveMA(ChessPieces pieces[PIECES_NUM], int selectId, int row, int col, int secondId);
    bool canMovePAO(ChessPieces pieces[PIECES_NUM], int selectId, int row, int col, int secondId);
    bool canMoveSHI(ChessPieces pieces[PIECES_NUM], int selectId, int row, int col, int secondId);
    bool canMoveXIANG(ChessPieces pieces[PIECES_NUM], int selectId, int row, int col, int secondId);
    // 判断棋子是否前后左右只移动了一个
    bool moveOneGrid(int fromRow, int fromCol, int row, int col);

    // 检查游戏是否结束
    void checkGameEnd();
    // 检查会不会面对面将军
    bool isGeneralFacingEachOther() const;
    // 检查是否被绝杀
    bool isCheckmate(bool isRed);
    // 无合法走法
    bool isStalemate(bool isRed);
    bool isRepetitionDraw();
    bool isMaterialDraw();

    // 生成所有可能的步骤
    void generateAllPossibleSteps(QVector<QSharedPointer<Step>>& steps,
        bool isMaximizingPlayer, ChessPieces pieces[PIECES_NUM]);
    // 生成将的可能移动步骤
    void generateJiangPossibleSteps(QVector<QSharedPointer<Step>>& steps, 
        const ChessPieces& piece, ChessPieces pieces[PIECES_NUM]);
    // 生成士的可能移动步骤
    void generateShiPossibleSteps(QVector<QSharedPointer<Step>>& steps, 
        const ChessPieces& piece, ChessPieces pieces[PIECES_NUM]);
    // 生成象的可能移动步骤
    void generateXiangPossibleSteps(QVector<QSharedPointer<Step>>& steps,
        const ChessPieces& piece, ChessPieces pieces[PIECES_NUM]);
    // 生成马的可能移动步骤
    void generateMaPossibleSteps(QVector<QSharedPointer<Step>>& steps,
        const ChessPieces& piece, ChessPieces pieces[PIECES_NUM]);
    // 生成兵的可能移动步骤
    void generateBingPossibleSteps(QVector<QSharedPointer<Step>>& steps,
        const ChessPieces& piece, ChessPieces pieces[PIECES_NUM]);
    // 车和炮移动步骤
    void addStraightSteps(QVector<QSharedPointer<Step>>& steps, int pieceId, 
        ChessPieces pieces[PIECES_NUM], int row, int col, bool isCannon = false);
    void checkAndAddStep(QVector<QSharedPointer<Step>>& steps, int pieceId, int row, int col,
        ChessPieces pieces[PIECES_NUM], int minRow = 0, 
        int maxRow = 9, int minCol = 0, int maxCol = 8);

    bool inspectOtherCheckJiang(ChessPieces pieces[PIECES_NUM], bool isRed);
    // 走棋模拟与回退
    void simulateMove(QSharedPointer<Step> step, ChessPieces pieces[PIECES_NUM]);
    void undoMove(QSharedPointer<Step> step, ChessPieces pieces[PIECES_NUM]);
    // 计算棋盘hash值
    quint64 calculateBoardHash() const;
    // 处理游戏结束
    void handleGameOver(GameResult res);
    void showResultBox(GameResult res);
    QString stepToString(const QSharedPointer<Step>& step);
    void printStepsFormatted(const QVector<QSharedPointer<Step>>& steps);
    void printChessPieces(ChessPieces* pieces);

    // 画棋盘
    void drawBoard(QPainter &painter);
    // 画棋子
    void drawPiece(QPainter &painter, int id);
    // 根据棋子行和列返回棋盘行列对应的坐标
    QPoint pieceCenter(int row, int col);
    // 根据棋子id返回棋盘行列对应的坐标
    QPoint pieceCenter(int id);
    // 根据棋子获取棋子矩形
    QRect pieceRect(int id);
    // 给定棋子行和列，得到id
    int getPieceId(int row, int col);
    // 执行悔棋
    void executeRetrack(bool isRed);
signals:
    void gameOver(GameResult res);
    // 子界面请求返回主菜单
    void requestReturnToMainMenu();
private slots:

};

#endif // BOARD_H
